package zy.blue7.common.vaildate.custom;


import lombok.Data;
import org.springframework.validation.Errors;
import org.springframework.validation.SmartValidator;
import zy.blue7.common.vaildate.ValidationAbstract;
import zy.blue7.common.vaildate.custom.rules.RuleInterface;

import java.util.List;

/**
 * @author blue7
 * @version 1.0
 * @date 2021/11/22 11:02
 */
@Data
public class CommonSmartValidator implements SmartValidator {


    /**
     * 一个对象入参可能有多个验证逻辑，所以设置多个校验规则
     */
    private List<RuleInterface> ruleInterfaces;

    public CommonSmartValidator(List<RuleInterface> ruleInterfaces) {
        this.ruleInterfaces = ruleInterfaces;
    }

    @Override
    public void validate(Object target, Errors errors, Object... validationHints) {
        doValidate((ValidationAbstract) target, errors, validationHints);
    }


    /**
     * 一次性搞定instanceof和isInstance，instanceof和isInstance长的非常像，用法也很类似，先看看这两个的用法：
     * <p>
     * obj.instanceof(class)
     * <p>
     * 也就是说这个对象是不是这种类型，
     * <p>
     * 1.一个对象是本身类的一个对象
     * <p>
     * 2.一个对象是本身类父类（父类的父类）和接口（接口的接口）的一个对象
     * <p>
     * 3.所有对象都是Object
     * <p>
     * 4.凡是null有关的都是false  null.instanceof(class)
     * <p>
     * <p>
     * <p>
     * class.inInstance(obj)
     * <p>
     * 这个对象能不能被转化为这个类
     * <p>
     * 1.一个对象是本身类的一个对象
     * <p>
     * 2.一个对象能被转化为本身类所继承类（父类的父类等）和实现的接口（接口的父接口）强转
     * <p>
     * 3.所有对象都能被Object的强转
     * <p>
     * 4.凡是null有关的都是false   class.inInstance(null)
     *
     * @param clazz
     * @return
     */
    @Override
    public boolean supports(Class<?> clazz) {
        return clazz.isInstance(ValidationAbstract.class);
    }

    @Override
    public void validate(Object target, Errors errors) {
        doValidate((ValidationAbstract) target, errors, null);
    }

    /**
     * 真正验证的时候
     *
     * @param target
     * @param errors
     * @param validationHints 分组
     */
    private void doValidate(ValidationAbstract target, Errors errors, Object[] validationHints) {

        /**
         * 一个 验证器中有多组规则， 遍历验证
         */
        ruleInterfaces.forEach(ruleInterface -> {
            ruleInterface.validate(target, errors, validationHints);
//      if (errors.hasErrors())
//        errors.reject(ruleInterface.getErrorCode(), "validate fail");
        });
    }
}
